package me.seu.demo.tbox;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Tbox 二进制解析
 *
 * @author: liangfeihu
 * @since: 2025/11/12 16:26
 */
public class TboxDataParser {

    // 信号定义类
    static class Signal {
        String name;
        int startBit;
        int length;
        String type;
        String initValue;
        String range;
        String expression;

        public Signal(String name, String startBit, String length, String type,
                      String initValue, String range, String expression) {
            this.name = name;
            this.startBit = Integer.parseInt(startBit);
            this.length = Integer.parseInt(length);
            this.type = type;
            this.initValue = initValue;
            this.range = range;
            this.expression = expression;
        }
    }

    // 事件定义类
    static class Event {
        String id;
        String name;
        List<Signal> signals = new ArrayList<>();

        public Event(String id, String name) {
            this.id = id;
            this.name = name;
        }
    }

    // 解析模板XML
    private static Map<String, Event> parseAnalysis(String analysisContent) throws Exception {
        Map<String, Event> eventMap = new HashMap<>();

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse(new ByteArrayInputStream(analysisContent.getBytes()));

        NodeList eventNodes = document.getElementsByTagName("Event");

        for (int i = 0; i < eventNodes.getLength(); i++) {
            Element eventElement = (Element) eventNodes.item(i);
            String eventId = eventElement.getAttribute("ID").replace("0x", "");

            String name = eventElement.getElementsByTagName("Name").item(0).getTextContent();
            Event event = new Event(eventId, name);

            int signalCount = Integer.parseInt(eventElement.getElementsByTagName("SignalCount").item(0).getTextContent());

            for (int j = 1; j <= signalCount; j++) {
                Element signalElement = (Element) eventElement.getElementsByTagName("Signal" + j).item(0);
                String signalContent = signalElement.getTextContent();

                // 解析信号定义
                String[] signalParts = signalContent.split("\",\"");
                if (signalParts.length >= 7) {
                    String signalName = signalParts[0].replace("\"", "");
                    String startBit = signalParts[1];
                    String length = signalParts[2];
                    String type = signalParts[3];
                    String initValue = signalParts[4];
                    String range = signalParts[5];
                    String expression = signalParts[6].replace("\"", "");

                    // 跳过预留字段和空信号
                    if (!signalName.contains("预留") && !signalName.trim().isEmpty() &&
                            !startBit.isEmpty() && !length.isEmpty()) {
                        Signal signal = new Signal(signalName, startBit, length, type, initValue, range, expression);
                        event.signals.add(signal);
                    } else {
                        System.out.println("跳过预留或空信号: " + signalName);
                    }
                }
            } // end signal
            eventMap.put(eventId, event);
        } // end event

        return eventMap;
    }

    // 按照新的位顺序重新映射位位置
    // 新的顺序: 7-0 15-8 23-16 31-24 39-32 47-40 55-48 63-56
    private static int remapBitPosition(int originalPosition) {
        // 计算原始位置所在的字节和位
        int originalByte = originalPosition / 8;
        int originalBitInByte = originalPosition % 8;

        // 按照新的顺序重新映射
        // 新顺序: 字节0(位7-0), 字节1(位15-8), 字节2(位23-16), 字节3(位31-24),
        //        字节4(位39-32), 字节5(位47-40), 字节6(位55-48), 字节7(位63-56)
        // 对于48位数据，我们只有6个字节，所以只需要处理0-5字节

        // 新位置 = (字节号 * 8) + (7 - 原始字节内位号)
        return originalByte * 8 + (7 - originalBitInByte);
    }

    // 解析16进制数据 - 按照事件ID切割信号
    private static List<Map<String, Object>> parseData(String dataContent, Map<String, Event> eventMap) {
        List<Map<String, Object>> result = new ArrayList<>();

        // 移除空格和换行
        String hexData = dataContent.replaceAll("\\s+", "");

        int position = 0;
        while (position < hexData.length()) {
            // 读取事件ID (2字节 = 4个十六进制字符)
            if (position + 4 > hexData.length()) {
                break;
            }

            String eventIdHex = hexData.substring(position, position + 4);
            String eventId = Integer.toString(Integer.parseInt(eventIdHex, 16));
            position += 4;

            // 检查是否是结束标记
            if ("65535".equals(eventId)) { // 0xFFFF
                System.out.println("遇到结束标记: 0xFFFF");
                break;
            }

            // 读取数据 (6字节 = 12个十六进制字符)
            if (position + 12 > hexData.length()) {
                break;
            }

            String dataHex = hexData.substring(position, position + 12);
            position += 12;

            // 获取事件定义
            Event event = eventMap.get(eventIdHex);
            if (event != null) {
                Map<String, Object> eventResult = new HashMap<>();
                Map<String, Object> signalsMap = new HashMap<>();
                List<Map<String, String>> signalsList = new ArrayList<>();

                // 将16进制数据转换为二进制字符串
                String binaryData = hexToBinary(dataHex);

                System.out.println("解析事件ID: " + eventId + " (" + event.name + "), 数据: " + dataHex);
                System.out.println("二进制数据: " + binaryData);

                for (Signal signal : event.signals) {
                    try {
                        String value = parseSignalValue(binaryData, signal);
                        if (value != null) {
                            Map<String, String> signalMap = new HashMap<>();
                            signalMap.put("Name", signal.name);
                            signalMap.put("Value", value);
                            signalsList.add(signalMap);
                            System.out.println("  信号: " + signal.name + " = " + value +
                                    " (原始起始位: " + signal.startBit + ", 长度: " + signal.length +
                                    ", 重新映射后起始位: " + remapBitPosition(signal.startBit) + ")");
                        }
                    } catch (Exception e) {
                        // 跳过解析错误的信号
                        System.err.println("  错误解析信号: " + signal.name + " - " + e.getMessage());
                    }
                } // end signal

                if (!signalsList.isEmpty()) {
                    signalsMap.put("signals", signalsList);
                    eventResult.put(event.name, signalsMap);
                    result.add(eventResult);
                }
            } else {
                // 跳过没有定义的事件ID
                System.out.println("跳过未定义的事件ID: " + eventId + " (0x" + eventIdHex + ")");
            }
        }

        return result;
    }

    // 16进制转二进制
    private static String hexToBinary(String hex) {
        StringBuilder binary = new StringBuilder();
        for (int i = 0; i < hex.length(); i++) {
            String hexChar = hex.substring(i, i + 1);
            int decimal = Integer.parseInt(hexChar, 16);
            String binaryChar = String.format("%4s", Integer.toBinaryString(decimal)).replace(' ', '0');
            binary.append(binaryChar);
        }
        return binary.toString();
    }

    // 解析信号值
    private static String parseSignalValue(String binaryData, Signal signal) {
        // 重新映射位位置
        int startPos = remapBitPosition(signal.startBit);
//        int startPos = signal.startBit;
//        int startPos = getStartBit(signal.startBit);
        int endPos = startPos + signal.length;

        if (endPos > binaryData.length() + 16) {
            throw new IllegalArgumentException("信号长度超过数据长度: " + signal.length + " > " + (binaryData.length() - startPos));
        }

        // 提取信号的二进制值
        String signalBinary = binaryData.substring(startPos - 16, endPos - 16);
        System.out.println("singleName+ " + signal.name + "=== signalBinary ===" + signalBinary);
        // 转换为数值
        BigInteger value;
        if ("SNM".equals(signal.type)) {
            // 有符号数处理
            if (signalBinary.charAt(0) == '1') {
                // 负数，计算补码
                StringBuilder complement = new StringBuilder();
                for (char c : signalBinary.toCharArray()) {
                    complement.append(c == '0' ? '1' : '0');
                }
                BigInteger complementValue = new BigInteger(complement.toString(), 2);
                value = complementValue.add(BigInteger.ONE).negate();
            } else {
                // 正数
                value = new BigInteger(signalBinary, 2);
            }
        } else {
            // 无符号数
            value = new BigInteger(signalBinary, 2);
        }

        // 应用表达式
        return applyExpression(value, signal.expression, signal.type);
    }

    //生成0-63的位置块，用于反转起始位置指向，小端模式的起始位转换成大端起始位。仅供参考，代码另外有更方便的换位实现。
    private static int getStartBit(int index) {
        // 动态生成数组：8 块，每块 8 个数
        int totalBlocks = 8;
        int blockSize = 8;
        int[] arr = new int[totalBlocks * blockSize];

        for (int k = 0; k < totalBlocks; k++) {
            int startValue = 8 * k + 7;  // 每块起始值：7,15,23,...
            for (int j = 0; j < blockSize; j++) {
                arr[8 * k + j] = startValue - j;  // 递减填充
            }
        }

        // 打印数组（可选）
        System.out.println("生成的数组：");
        for (int i = 0; i < arr.length; i++) {
            System.out.printf("arr[%2d] = %2d\n", i, arr[i]);
        }

        // 用户输入
        while (true) {
            System.out.print("\n请输入索引 (0-63)，输入 -1 退出: ");
            if (index >= 0 && index < arr.length) {
                System.out.println("值为: " + arr[index]);
                return arr[index];
            } else {
                System.out.println("索引超出范围！请输入 0 到 63 之间的数。");
            }
        }

    }

    // 应用表达式
    private static String applyExpression(BigInteger value, String expression, String type) {
        if (expression.startsWith("E=")) {
            String expr = expression.substring(2);
            int result = calculate(expr, value.intValue());
            return String.valueOf(result);
        } else if (expression.contains("=") && !expression.startsWith("E=")) {
            // 处理枚举类型
            if ("ENM".equals(type)) {
                String[] enumParts = expression.split(";");
                for (String enumPart : enumParts) {
                    String[] keyValue = enumPart.split("=");
                    if (keyValue.length == 2) {
                        String key = keyValue[0].trim();
                        String desc = keyValue[1].trim();
                        // 检查是否是十六进制值
                        if (key.startsWith("0x")) {
                            if (key.substring(2).equalsIgnoreCase(value.toString(16))) {
                                return desc;
                            }
                        } else if (key.equals(value.toString())) {
                            return desc;
                        }
                    }
                }
                // 如果没有匹配的枚举值，返回原始值
                return value.toString();
            }
        }

        // 默认返回原始值
        return value.toString();
    }


    /**
     * 计算表达式结果
     *
     * @param expression 表达式字符串（如 "N*5+20"）
     * @param n          输入整数
     * @return 计算结果
     */
    public static int calculate(String expression, int n) {
        // 替换表达式中的 N 为输入值
        String processedExpr = expression.replace("N", String.valueOf(n));

        // 将表达式拆分为操作数和操作符
        List<String> tokens = tokenizeExpression(processedExpr);

        // 先处理乘除（* 和 /）
        List<String> afterMulDiv = processMultiplicationDivision(tokens);

        // 再处理加减（+ 和 -）
        return processAdditionSubtraction(afterMulDiv);
    }

    /**
     * 拆分表达式为操作数和操作符
     * 例如 "1000*5+20" → ["1000", "*", "5", "+", "20"]
     */
    private static List<String> tokenizeExpression(String expr) {
        List<String> tokens = new ArrayList<>();
        StringBuilder current = new StringBuilder();

        for (int i = 0; i < expr.length(); i++) {
            char c = expr.charAt(i);

            // 如果是操作符（+ - * /）或数字结束
            if (c == '+' || c == '-' || c == '*' || c == '/') {
                if (current.length() > 0) {
                    tokens.add(current.toString());
                    current.setLength(0);
                }
                tokens.add(String.valueOf(c));
            } else {
                current.append(c);
            }
        }

        // 添加最后一个操作数
        if (current.length() > 0) {
            tokens.add(current.toString());
        }

        return tokens;
    }

    /**
     * 处理乘法和除法（优先级更高）
     */
    private static List<String> processMultiplicationDivision(List<String> tokens) {
        List<String> result = new ArrayList<>();
        int i = 0;

        // 处理第一个操作数
        result.add(tokens.get(0));
        i = 1;

        while (i < tokens.size()) {
            String op = tokens.get(i);
            String nextNum = tokens.get(i + 1);

            if (op.equals("*") || op.equals("/")) {
                // 取上一个操作数和当前操作数
                int left = Integer.parseInt(result.get(result.size() - 1));
                int right = Integer.parseInt(nextNum);

                int newValue;
                if (op.equals("*")) {
                    newValue = left * right;
                } else { // 除法
                    // 整数除法（向0取整，符合Java规则）
                    newValue = left / right;
                }

                // 替换上一个操作数
                result.set(result.size() - 1, String.valueOf(newValue));
                i += 2; // 跳过操作符和下一个操作数
            } else {
                // 非乘除操作符，直接添加
                result.add(op);
                result.add(nextNum);
                i += 2;
            }
        }
        return result;
    }

    /**
     * 处理加法和减法（最后处理）
     */
    private static int processAdditionSubtraction(List<String> tokens) {
        int result = Integer.parseInt(tokens.get(0));
        for (int i = 1; i < tokens.size(); i += 2) {
            String op = tokens.get(i);
            int num = Integer.parseInt(tokens.get(i + 1));

            if (op.equals("+")) {
                result += num;
            } else if (op.equals("-")) {
                result -= num;
            }
        }
        return result;
    }

    public static void main(String[] args) {
        try {
            // 读取文件
            String analysisContent = new String(java.nio.file.Files.readAllBytes(
                    java.nio.file.Paths.get("/Users/a123/codes/myown/learning-demo/common-demo/src/main/resources/tbox/analysis.txt")));
            String dataContent = new String(java.nio.file.Files.readAllBytes(
                    java.nio.file.Paths.get("/Users/a123/codes/myown/learning-demo/common-demo/src/main/resources/tbox/1028.txt")));

            System.out.println("开始解析模板...");
            // 解析模板
            Map<String, Event> eventMap = parseAnalysis(analysisContent);
            System.out.println("从分析模板中解析了 " + eventMap.size() + " 个事件");

            System.out.println("\n开始解析数据...");
            // 解析数据
            List<Map<String, Object>> parsedData = parseData(dataContent, eventMap);
            System.out.println("\n从数据文件中解析了 " + parsedData.size() + " 条数据记录");
            System.out.println("数据记录的详细信息如下：" + JSONObject.toJSONString(parsedData));

            // 创建JSON
            ObjectMapper mapper = new ObjectMapper();
            ObjectNode root = mapper.createObjectNode();
            ArrayNode dataAnalysis = mapper.createArrayNode();

            for (Map<String, Object> record : parsedData) {
                ObjectNode recordNode = mapper.valueToTree(record);
                dataAnalysis.add(recordNode);
            }

            root.set("dataAnalysis", dataAnalysis);

            // 输出JSON到文件
            String jsonOutput = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(root);

            // 将JSON数据完整打印到控制台
            System.out.println("\n=== 解析后的完整JSON数据 ===");
            System.out.println(jsonOutput);

            java.nio.file.Files.write(
                    java.nio.file.Paths.get("output_new.json"),
                    jsonOutput.getBytes()
            );

            System.out.println("\nJSON输出已写入到 output_new.json 文件");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}